Scripts {pliman} 67ª RBRAS e 20º SEAGRO
1 Pacotes
2 Importação e manipulação
3 Segmentação
## [1] "R" "G" "B" "NR" "NG" "NB" "GB" "RB" "GR"
## [10] "BI" "BIM" "SCI" "GLI" "HI" "NGRDI" "NDGBI" "NDRBI" "I"
## [19] "S" "VARI" "HUE" "HUE2" "BGI" "L" "GRAY" "GLAI" "CI"
## [28] "SHP" "RI" "G-B" "G-R" "R-G" "R-B" "B-R" "B-G" "DGCI"
## [37] "GRAY2" "L*" "a" "b*" "L*-a" "L*-b" "b*-a"
# Segmentação utilizando threshold adaptativo
image_segment(adaptive,
index = "R",
# filter = 5,
# fill_hull = TRUE,
threshold = "adaptive")4 Análise de objetos
4.1 Imagem única
grains <- image_import("grains.jpg", plot = TRUE)
# Analisar os objetos
res <- analyze_objects(grains, index = "GRAY")# Algumas funcionalidades
res <-
analyze_objects(grains,
index = "GRAY",
lower_noise = 0.4, # remove ruídos maiores
show_contour = FALSE,
marker = "point")res <-
analyze_objects(grains,
index = "GRAY",
topn_upper = 10, # Somente os 10 maiores grãos
show_contour = FALSE,
marker = "point")4.2 Processamento em lote com correção (referência)
4.2.1 Pelo tamanho da referência
# Analisar os objetos
res <-
analyze_objects(pattern = "P",
dir_original = "flax_grain", # subpasta com as imagens originais
dir_processed = "proc", # subpasta com as imagens processadas
reference = TRUE, # indica que há uma referência
reference_larger = TRUE, # indica que a referência é o maior objeto
reference_area = 6, # a referência tem 6 cm2
index = "GRAY",
show_contour = FALSE,
marker = "point",
plot = FALSE,
save_image = TRUE)## Processing image P01 |======= | 17% 00:00:00
## Processing image P02 |============== | 33% 00:00:03
## Processing image P03 |====================== | 50% 00:00:07
## Processing image P04 |============================= | 67% 00:00:11
## Processing image P05 |==================================== | 83% 00:00:13
## Processing image P06 |===========================================| 100% 00:00:16
## --------------------------------------------
## Image Objects
## P01 277
## P02 91
## P03 179
## P04 112
## P05 22
## P06 78
## --------------------------------------------
4.2.2 Pela cor da referência
flax <- image_import("flax_af/A2_32_3.jpg", plot = TRUE)
# Índice para segmentar a referência e folhas do fundo
image_segment_iter(flax,
index = c("R/(G/B)", "B-R"),
ncol = 3)## image pixels percent
## 1 original 806490 100.00000
## 2 seg1 129657 16.07670
## 3 seg2 38517 29.70684
# Note que agora o processamento é realizado de forma paralela
res <-
analyze_objects(pattern = "A",
dir_original = "flax_af",
reference = TRUE,
reference_area = 20,
back_fore_index = "R/(G/B)",
fore_ref_index = "B-R",
watershed = FALSE,
filter = 2,
plot = FALSE,
parallel = TRUE)## --------------------------------------------
## Image Objects
## A1_28_1 18
## A1_28_2 28
## A1_28_3 28
## A10_90_1 149
## A10_90_2 116
## A10_90_3 77
## A11_98_1 132
## A11_98_2 151
## A11_98_3 119
## A12_105_1 110
## A12_105_2 127
## A12_105_3 154
## A2_32_1 23
## A2_32_2 25
## A2_32_3 31
## A3_42_1 39
## A3_42_2 47
## A3_42_3 52
## A4_46_1 58
## A4_46_2 38
## A4_46_3 56
## A5_55_1 53
## A5_55_2 74
## A5_55_3 61
## A6_63_1 68
## A6_63_2 105
## A6_63_3 83
## A7_70_1 98
## A7_70_2 111
## A7_70_3 112
## A8_76_1 113
## A8_76_2 118
## A8_76_3 114
## A9_83_1 120
## A9_83_2 89
## A9_83_3 101
## --------------------------------------------
merged <- get_measures(res)
# Organizar os dados para ajuste do modelo Logístico
df_plot <-
merged$summary |>
separate_col(img,
into = c("avaliacao", "das", "bloco")) |>
mutate(das = as.numeric(das))
formula <- y ~ b1/(1 + exp(b2 - b3 * x))
ggplot(df_plot, aes(das, area_sum)) +
geom_smooth(method = "nls",
method.args = list(formula = formula,
start = c(b1 = 248,
b2 = 6,
b3 = 0.07)),
se = FALSE,
color = "red") +
stat_summary(fun.data = mean_se,
geom = "errorbar",
width = 0.5) +
stat_summary(fun = mean,
geom = "point",
col = "blue",
size = 3) +
scale_x_continuous(breaks = unique(df_plot$das)) +
scale_y_continuous(breaks = seq(0, 150, by = 25)) +
labs(x = "Dias após a semeadura",
y = expression(Área~foliar~média~(cm^2~planta^{-1}))) +
theme_bw(base_size = 16) +
theme(panel.grid = element_blank()) 5 Ortomosaicos
Imagens disponibilizadas por Filipe Matias, no github do FIELDimageR
5.1 Cobertura vegetal (canopy)
# preparar a imagem
# Somente iterativo
# prep <- image_prepare_mv(img)
prep <-
img |>
image_rotate(-2.076, plot = FALSE) |>
image_crop(width = 194:1075,
height = 143:379,
plot = TRUE)res <-
analyze_objects_shp(prep,
nrow = 16,
ncol = 9,
index = "HUE",
object_index = c("NGRDI", "DGCI"))
# cobertura de solo
plot_index_shp(res)5.2 Índices de vegetação
5.3 Stand de plantas
res <-
analyze_objects_shp(stand,
index = "NGRDI",
invert = TRUE,
nrow = 7,
ncol = 1)
par(mfrow = c(1, 2))
# cobertura de solo
plot_index_shp(res)
# mapeamento das plantas (distâncias e CV(%))
object_mark(res)
mapped <- object_map(res)
# coeficiente de variação dentro da linha
barplot(mapped$cvs)6 Fitopatometria
6.1 Iterativa
6.2 Usando paletas
sev <-
measure_disease(folha,
img_healthy = pals$soja_h.png, # paleta para folha sadia
img_symptoms = pals$soja_s.png, # paleta para folha doente
img_background = pals$soja_b.png) # paleta para fundo6.3 Usando índices de imagem
# Índice para segmentar a folha do fundo, depois a doença da folha
image_segment_iter(folha,
index = c("B", "NGRDI"),
ncol = 3)## image pixels percent
## 1 original 4813707 100.00000
## 2 seg1 2781900 57.79122
## 3 seg2 384237 13.81203
# IMPORTANTE: theshold vai alterar a severidade
sev2 <-
measure_disease(folha,
index_lb = "B", # índice para segmentar a folha do fundo
index_dh = "NGRDI", # índice para segmentar folha doente e sadia
threshold = c("Otsu", 0)) # threshold para os dois índices, respectivamente# em lote (utilizando as paletas)
sev3 <-
measure_disease(pattern = "soy_",
dir_original = "soybean_rust", # pasta com as imagens originais
dir_processed = "proc_rust", # pasta com as imagens processadas
save_image = TRUE,
plot = FALSE,
img_healthy = pals$soja_h.png,
img_symptoms = pals$soja_s.png,
img_background = pals$soja_b.png,
parallel = TRUE)
# standard area diagrams
sad(sev3, n = 6)sev4 <-
measure_disease(pattern = "soy_",
dir_original = "soybean_rust",
plot = FALSE,
index_lb = "B",
index_dh = "NGRDI",
threshold = c("Otsu", 0),
parallel = TRUE)
# paletas vs índices de imagem
df <-
data.frame(paletas = sev3$severity$symptomatic,
índices = sev4$severity$symptomatic)
dfggplot(df, aes(paletas, índices)) +
geom_point() +
geom_abline(intercept = 0, slope = 1, color = "red") +
theme_bw(base_size = 16) +
xlim(0, 100) +
ylim(0, 100) +
coord_equal()Universidade Federal de Santa Catarina, https://olivoto.netlify.app/↩︎
LS0tDQp0aXRsZTogIlNjcmlwdHMge3BsaW1hbn0gNjfCqiBSQlJBUyBlIDIwwrogU0VBR1JPIg0KYXV0aG9yOg0KICAtIFRpYWdvIE9saXZvdG9eW1VuaXZlcnNpZGFkZSBGZWRlcmFsIGRlIFNhbnRhIENhdGFyaW5hLCBodHRwczovL29saXZvdG8ubmV0bGlmeS5hcHAvXQ0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjoNCiAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgbGlnaHRib3g6IHRydWUNCiAgICBnYWxsZXJ5OiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQoNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICBlcnJvciA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjYWNoZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQ0KDQpgYGANCg0KWyFbXShsb2dvLnBuZyldKGh0dHBzOi8vNjdyYnJhczIwc2VhZ3JvLmNvbS5ici8pDQoNCiMgUGFjb3Rlcw0KDQpgYGB7cn0NCmxpYnJhcnkocGxpbWFuKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpzZXR3ZCgiRDovRGVza3RvcC9VRlNDL2N1cnNvcy9wbGltYW42N3JicmFzIikNCnNldF93ZF9oZXJlKCkNCiMgc2V0X3BsaW1hbl92aWV3ZXIoIm1hcHZpZXciKQ0KDQpgYGANCg0KIyBJbXBvcnRhw6fDo28gZSBtYW5pcHVsYcOnw6NvDQojIyBJbXBvcnRhw6fDo28NCmBgYHtyfQ0KbGVhdmVzIDwtIGltYWdlX2ltcG9ydCgibGVhdmVzLmpwZyIsIHBsb3QgPSBUUlVFKQ0KDQpgYGANCg0KIyMgUmVzb2x1w6fDo28NCmBgYHtyIGV2YWw9RkFMU0V9DQpkcGkobGVhdmVzLCB2aWV3ZXIgPSAibWFwdmlldyIpDQpgYGANCg0KDQojIyBDb3J0YXIsIGdpcmFyIGUgcmVkaW1lbnNpb25hcg0KYGBge3J9DQpjcm9wIDwtIGltYWdlX2F1dG9jcm9wKGxlYXZlcywgcGxvdCA9IFRSVUUpDQojIGNyb3AgPC0gaW1hZ2VfY3JvcChsZWF2ZXMsIHZpZXdlciA9ICJtYXB2aWV3IikNCg0KY3JvcCA8LSBpbWFnZV9jcm9wKGxlYXZlcywNCiAgICAgICAgICAgICAgICAgICBwbG90ID0gVFJVRSkNCmBgYA0KDQoNCiMgU2VnbWVudGHDp8Ojbw0KYGBge3J9DQojIMONbmRpY2VzIHBhcmEgc2VnbWVudGHDp8Ojbw0KcGxpbWFuX2luZGV4ZXMoKQ0KaW5kZXggPC0gaW1hZ2VfaW5kZXgobGVhdmVzLCBpbmRleCA9IGMoIlIiLCAiRyIsICJCIiwgIkItUiIpKQ0KcGxvdChpbmRleCwgdHlwZSA9ICJkZW5zaXR5IikNCg0KIyBJbWFnZW0gYmluw6FyaWENCmJpbmFyeSA8LSBpbWFnZV9iaW5hcnkobGVhdmVzLCBpbmRleCA9ICJCLVIiKQ0KYmluYXJ5IDwtIA0KICBpbWFnZV9iaW5hcnkobGVhdmVzLA0KICAgICAgICAgICAgICAgaW5kZXggPSAiQi1SIiwNCiAgICAgICAgICAgICAgIGludmVydCA9IFRSVUUpDQpiaW5hcnkgPC0gDQogIGltYWdlX2JpbmFyeShsZWF2ZXMsIA0KICAgICAgICAgICAgICAgaW5kZXggPSAiQi1SIiwNCiAgICAgICAgICAgICAgIGZpbGxfaHVsbCA9IFRSVUUpDQpiaW5hcnkgPC0gDQogIGltYWdlX2JpbmFyeShsZWF2ZXMsIA0KICAgICAgICAgICAgICAgaW5kZXggPSAiQi1SIiwNCiAgICAgICAgICAgICAgIGZpbHRlciA9IDUsDQogICAgICAgICAgICAgICBmaWxsX2h1bGwgPSBUUlVFKQ0KDQojIFNlZ21lbnRhw6fDo28NCnNlZyA8LSANCiAgaW1hZ2Vfc2VnbWVudChsZWF2ZXMsDQogICAgICAgICAgICAgICAgIyB0aHJlc2hvbGQgPSAwLjEsDQogICAgICAgICAgICAgICAgIyB0aHJlc2hvbGQgPSAiYWEiLA0KICAgICAgICAgICAgICAgIGluZGV4ID0gIkItUiIpDQoNCiMgVGhyZXNob2xkIGFkYXB0YXRpdm8NCmFkYXB0aXZlIDwtIGltYWdlX2ltcG9ydCgiYWRhcHRpdmUuanBnIiwgcGxvdCA9IFRSVUUpDQoNCiMgw4xuZGljZSBkZSBpbWFnZW0NCmluZCA8LSBpbWFnZV9pbmRleChhZGFwdGl2ZSwgaW5kZXggPSAiUiIpDQpwbG90KGluZCwgdHlwZSA9ICJkZW5zaXR5IikNCg0KIyBTZWdtZW50YcOnw6NvIHBvciBPdHN1DQppbWFnZV9zZWdtZW50KGFkYXB0aXZlLCBpbmRleCA9ICJSIikNCg0KIyBTZWdtZW50YcOnw6NvIHV0aWxpemFuZG8gdGhyZXNob2xkIGFkYXB0YXRpdm8NCmltYWdlX3NlZ21lbnQoYWRhcHRpdmUsDQogICAgICAgICAgICAgIGluZGV4ID0gIlIiLA0KICAgICAgICAgICAgICAjIGZpbHRlciA9IDUsDQogICAgICAgICAgICAgICMgZmlsbF9odWxsID0gVFJVRSwNCiAgICAgICAgICAgICAgdGhyZXNob2xkID0gImFkYXB0aXZlIikNCmBgYA0KDQoNCg0KIyBBbsOhbGlzZSBkZSBvYmpldG9zDQojIyBJbWFnZW0gw7puaWNhDQpgYGB7cn0NCmdyYWlucyA8LSBpbWFnZV9pbXBvcnQoImdyYWlucy5qcGciLCBwbG90ID0gVFJVRSkNCg0KIyBBbmFsaXNhciBvcyBvYmpldG9zDQpyZXMgPC0gYW5hbHl6ZV9vYmplY3RzKGdyYWlucywgaW5kZXggPSAiR1JBWSIpDQpyZXMkc3RhdGlzdGljcw0KDQojIEFsZ3VtYXMgZnVuY2lvbmFsaWRhZGVzDQpyZXMgPC0gDQogIGFuYWx5emVfb2JqZWN0cyhncmFpbnMsIA0KICAgICAgICAgICAgICAgICAgaW5kZXggPSAiR1JBWSIsDQogICAgICAgICAgICAgICAgICBsb3dlcl9ub2lzZSA9IDAuNCwgICAgICAjIHJlbW92ZSBydcOtZG9zIG1haW9yZXMNCiAgICAgICAgICAgICAgICAgIHNob3dfY29udG91ciA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgbWFya2VyID0gInBvaW50IikNCnBsb3QocmVzKQ0KDQpyZXMgPC0gDQogIGFuYWx5emVfb2JqZWN0cyhncmFpbnMsIA0KICAgICAgICAgICAgICAgICAgaW5kZXggPSAiR1JBWSIsDQogICAgICAgICAgICAgICAgICB0b3BuX3VwcGVyID0gMTAsICAgICAgICAjIFNvbWVudGUgb3MgMTAgbWFpb3JlcyBncsOjb3MNCiAgICAgICAgICAgICAgICAgIHNob3dfY29udG91ciA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgbWFya2VyID0gInBvaW50IikNCg0KYGBgDQoNCg0KIyMgUHJvY2Vzc2FtZW50byBlbSBsb3RlIGNvbSBjb3JyZcOnw6NvIChyZWZlcsOqbmNpYSkNCiMjIyBQZWxvIHRhbWFuaG8gZGEgcmVmZXLDqm5jaWENCmBgYHtyfQ0KIyBBbmFsaXNhciBvcyBvYmpldG9zDQpyZXMgPC0gDQogIGFuYWx5emVfb2JqZWN0cyhwYXR0ZXJuID0gIlAiLA0KICAgICAgICAgICAgICAgICAgZGlyX29yaWdpbmFsID0gImZsYXhfZ3JhaW4iLCAgICAjIHN1YnBhc3RhIGNvbSBhcyBpbWFnZW5zIG9yaWdpbmFpcw0KICAgICAgICAgICAgICAgICAgZGlyX3Byb2Nlc3NlZCA9ICJwcm9jIiwgICAgICAgICAjIHN1YnBhc3RhIGNvbSBhcyBpbWFnZW5zIHByb2Nlc3NhZGFzDQogICAgICAgICAgICAgICAgICByZWZlcmVuY2UgPSBUUlVFLCAgICAgICAgICAgICAgICMgaW5kaWNhIHF1ZSBow6EgdW1hIHJlZmVyw6puY2lhDQogICAgICAgICAgICAgICAgICByZWZlcmVuY2VfbGFyZ2VyID0gVFJVRSwgICAgICAgICMgaW5kaWNhIHF1ZSBhIHJlZmVyw6puY2lhIMOpIG8gbWFpb3Igb2JqZXRvIA0KICAgICAgICAgICAgICAgICAgcmVmZXJlbmNlX2FyZWEgPSA2LCAgICAgICAgICAgICAjIGEgcmVmZXLDqm5jaWEgdGVtIDYgY20yDQogICAgICAgICAgICAgICAgICBpbmRleCA9ICJHUkFZIiwNCiAgICAgICAgICAgICAgICAgIHNob3dfY29udG91ciA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgbWFya2VyID0gInBvaW50IiwNCiAgICAgICAgICAgICAgICAgIHBsb3QgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgIHNhdmVfaW1hZ2UgPSBUUlVFKQ0KDQpoaXN0KHJlcyRyZXN1bHRzJGxlbmd0aCkNCg0KYGBgDQoNCg0KIyMjIFBlbGEgY29yIGRhIHJlZmVyw6puY2lhDQpgYGB7cn0NCiN8IG91dC13aWR0aDogIjEwMCUiDQpmbGF4IDwtIGltYWdlX2ltcG9ydCgiZmxheF9hZi9BMl8zMl8zLmpwZyIsIHBsb3QgPSBUUlVFKQ0KDQojIMONbmRpY2UgcGFyYSBzZWdtZW50YXIgYSByZWZlcsOqbmNpYSBlIGZvbGhhcyBkbyBmdW5kbw0KaW1hZ2Vfc2VnbWVudF9pdGVyKGZsYXgsIA0KICAgICAgICAgICAgICAgICAgIGluZGV4ID0gYygiUi8oRy9CKSIsICJCLVIiKSwNCiAgICAgICAgICAgICAgICAgICBuY29sID0gMykNCg0KDQojIE5vdGUgcXVlIGFnb3JhIG8gcHJvY2Vzc2FtZW50byDDqSByZWFsaXphZG8gZGUgZm9ybWEgcGFyYWxlbGENCnJlcyA8LQ0KICBhbmFseXplX29iamVjdHMocGF0dGVybiA9ICJBIiwNCiAgICAgICAgICAgICAgICAgIGRpcl9vcmlnaW5hbCA9ICJmbGF4X2FmIiwNCiAgICAgICAgICAgICAgICAgIHJlZmVyZW5jZSA9IFRSVUUsDQogICAgICAgICAgICAgICAgICByZWZlcmVuY2VfYXJlYSA9IDIwLA0KICAgICAgICAgICAgICAgICAgYmFja19mb3JlX2luZGV4ID0gIlIvKEcvQikiLA0KICAgICAgICAgICAgICAgICAgZm9yZV9yZWZfaW5kZXggPSAiQi1SIiwNCiAgICAgICAgICAgICAgICAgIHdhdGVyc2hlZCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgZmlsdGVyID0gMiwNCiAgICAgICAgICAgICAgICAgIHBsb3QgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgIHBhcmFsbGVsID0gVFJVRSkNCg0KbWVyZ2VkIDwtIGdldF9tZWFzdXJlcyhyZXMpDQoNCg0KIyBPcmdhbml6YXIgb3MgZGFkb3MgcGFyYSBhanVzdGUgZG8gbW9kZWxvIExvZ8Otc3RpY28NCmRmX3Bsb3QgPC0gDQogIG1lcmdlZCRzdW1tYXJ5IHw+IA0KICBzZXBhcmF0ZV9jb2woaW1nLCANCiAgICAgICAgICAgICAgIGludG8gPSBjKCJhdmFsaWFjYW8iLCAiZGFzIiwgImJsb2NvIikpIHw+IA0KICBtdXRhdGUoZGFzID0gYXMubnVtZXJpYyhkYXMpKQ0KDQpmb3JtdWxhIDwtIHkgfiBiMS8oMSArIGV4cChiMiAtIGIzICogeCkpDQoNCmdncGxvdChkZl9wbG90LCBhZXMoZGFzLCBhcmVhX3N1bSkpICsgDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJubHMiLA0KICAgICAgICAgICAgICBtZXRob2QuYXJncyA9IGxpc3QoZm9ybXVsYSA9IGZvcm11bGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydCA9IGMoYjEgPSAyNDgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYjIgPSA2LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGIzID0gMC4wNykpLA0KICAgICAgICAgICAgICBzZSA9IEZBTFNFLA0KICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiKSArDQogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IG1lYW5fc2UsDQogICAgICAgICAgICAgICBnZW9tID0gImVycm9yYmFyIiwNCiAgICAgICAgICAgICAgIHdpZHRoID0gMC41KSArDQogIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLA0KICAgICAgICAgICAgICAgZ2VvbSA9ICJwb2ludCIsDQogICAgICAgICAgICAgICBjb2wgPSAiYmx1ZSIsDQogICAgICAgICAgICAgICBzaXplID0gMykgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gdW5pcXVlKGRmX3Bsb3QkZGFzKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDE1MCwgYnkgPSAyNSkpICsNCiAgbGFicyh4ID0gIkRpYXMgYXDDs3MgYSBzZW1lYWR1cmEiLA0KICAgICAgIHkgPSBleHByZXNzaW9uKMOBcmVhfmZvbGlhcn5tw6lkaWF+KGNtXjJ+cGxhbnRhXnstMX0pKSkgKw0KICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNikgKw0KICB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpKSANCg0KYGBgDQoNCg0KDQojIE9ydG9tb3NhaWNvcw0KSW1hZ2VucyBkaXNwb25pYmlsaXphZGFzIHBvciBGaWxpcGUgTWF0aWFzLCBubyBnaXRodWIgZG8gW0ZJRUxEaW1hZ2VSXShSaHR0cHM6Ly9naXRodWIuY29tL09wZW5Ecm9uZU1hcC9GSUVMRGltYWdlUikNCg0KIyMgQ29iZXJ0dXJhIHZlZ2V0YWwgKGNhbm9weSkNCg0KYGBge3J9DQojIGltYWdlbQ0KaW1nIDwtIA0KICBpbWFnZV9pbXBvcnQoInBvdGF0b2VzLnRpZiIsIHBhdGggPSAib3J0aG9tb3NhaWMiKSB8PiANCiAgaW1hZ2VfaG9yaXpvbnRhbCgpDQoNCnBsb3QoaW1nKQ0KDQojIHByZXBhcmFyIGEgaW1hZ2VtDQojIFNvbWVudGUgaXRlcmF0aXZvDQojIHByZXAgPC0gaW1hZ2VfcHJlcGFyZV9tdihpbWcpDQpwcmVwIDwtIA0KICBpbWcgfD4gDQogIGltYWdlX3JvdGF0ZSgtMi4wNzYsIHBsb3QgPSBGQUxTRSkgfD4gDQogIGltYWdlX2Nyb3Aod2lkdGggPSAxOTQ6MTA3NSwNCiAgICAgICAgICAgICBoZWlnaHQgPSAxNDM6Mzc5LA0KICAgICAgICAgICAgIHBsb3QgPSBUUlVFKQ0KDQoNCiMgw61uZGljZSBwYXJhIHNlZ21lbnRhw6fDo28NCmltYWdlX2luZGV4KHByZXAsIGluZGV4ID0gICJIVUUiKQ0KDQoNCnJlcyA8LSANCiAgYW5hbHl6ZV9vYmplY3RzX3NocChwcmVwLA0KICAgICAgICAgICAgICAgICAgICAgIG5yb3cgPSAxNiwNCiAgICAgICAgICAgICAgICAgICAgICBuY29sID0gOSwNCiAgICAgICAgICAgICAgICAgICAgICBpbmRleCA9ICJIVUUiLA0KICAgICAgICAgICAgICAgICAgICAgIG9iamVjdF9pbmRleCA9IGMoIk5HUkRJIiwgIkRHQ0kiKSkNCg0KIyBjb2JlcnR1cmEgZGUgc29sbw0KcGxvdF9pbmRleF9zaHAocmVzKQ0KDQojIHJlc3VtaXIgYXMgaW5mb3JtYcOnw7Vlcw0KcmVzdWx0cyA8LSBnZXRfbWVhc3VyZXMocmVzKQ0KYGBgDQoNCg0KDQojIyDDjW5kaWNlcyBkZSB2ZWdldGHDp8Ojbw0KDQpgYGB7cn0NCiMgTsOtdmVsIGRlIHBhcmNlbGENCnBsb3RfaW5kZXhfc2hwKHJlcywgYXR0cmlidXRlID0gIk5HUkRJIikNCg0KIyBOw612ZWwgZGUgcGl4ZWwNCnBsb3RfaW5kZXgob2JqZWN0ID0gcmVzLCBpbmRleCA9ICJER0NJIikNCiMgcGxvdF9pbmRleChvYmplY3QgPSByZXMsIGluZGV4ID0gIkRHQ0kiLCB2aWV3ZXIgPSAibWFwIikNCg0KIyByZXN1bWlyIGFzIGluZm9ybWHDp8O1ZXMNCnJlc3VsdHMgPC0gZ2V0X21lYXN1cmVzKHJlcykNCmBgYA0KDQoNCiMjIFN0YW5kIGRlIHBsYW50YXMNCg0KYGBge3J9DQojIGltYWdlbQ0Kc3RhbmQgPC0gaW1hZ2VfaW1wb3J0KCJzdGFuZC5qcGciLCBwYXRoID0gIm9ydGhvbW9zYWljIiwgcGxvdCA9IFRSVUUpDQoNCg0KIyDDrW5kaWNlIHBhcmEgc2VnbWVudGHDp8Ojbw0KaW1hZ2Vfc2VnbWVudChzdGFuZCwgIkhVRSIpDQppbWFnZV9zZWdtZW50KHN0YW5kLCAiTkdSREkiKQ0KaW1hZ2Vfc2VnbWVudChzdGFuZCwgIk5HUkRJIiwgaW52ZXJ0ID0gVFJVRSkNCg0KcmVzIDwtIA0KICBhbmFseXplX29iamVjdHNfc2hwKHN0YW5kLA0KICAgICAgICAgICAgICAgICAgICAgIGluZGV4ID0gIk5HUkRJIiwNCiAgICAgICAgICAgICAgICAgICAgICBpbnZlcnQgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgIG5yb3cgPSA3LA0KICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAxKQ0KDQpwYXIobWZyb3cgPSBjKDEsIDIpKQ0KIyBjb2JlcnR1cmEgZGUgc29sbw0KcGxvdF9pbmRleF9zaHAocmVzKQ0KDQojIG1hcGVhbWVudG8gZGFzIHBsYW50YXMgKGRpc3TDom5jaWFzIGUgQ1YoJSkpDQpvYmplY3RfbWFyayhyZXMpDQptYXBwZWQgPC0gIG9iamVjdF9tYXAocmVzKQ0KDQojIGNvZWZpY2llbnRlIGRlIHZhcmlhw6fDo28gZGVudHJvIGRhIGxpbmhhDQpiYXJwbG90KG1hcHBlZCRjdnMpDQoNCnBhcihtZnJvdyA9IGMoMSwgMSkpDQpgYGANCg0KDQoNCiMgRml0b3BhdG9tZXRyaWENCiMjIEl0ZXJhdGl2YQ0KYGBge3J9DQpmb2xoYSA8LSBpbWFnZV9wbGltYW4oInNldl9sZWFmLmpwZyIsIHBsb3QgPSBUUlVFKQ0KIyBtZWFzdXJlX2Rpc2Vhc2VfaXRlcihmb2xoYSwgdmlld2VyID0gIm1hcHZpZXciKQ0KDQpgYGANCg0KDQojIyBVc2FuZG8gcGFsZXRhcw0KYGBge3J9DQpmb2xoYSA8LSBpbWFnZV9pbXBvcnQoInNveWJlYW5fcnVzdC9zb3lfMS5qcGciLCBwbG90ID0gVFJVRSkNCnBhbHMgPC0gaW1hZ2VfaW1wb3J0KHBhdHRlcm4gPSAic29qYV8iLA0KICAgICAgICAgICAgICAgICAgICAgcGF0aCA9ICJzb3liZWFuX3J1c3QiLA0KICAgICAgICAgICAgICAgICAgICAgcGxvdCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICBuY29sID0gMykNCnNldiA8LSANCiAgbWVhc3VyZV9kaXNlYXNlKGZvbGhhLA0KICAgICAgICAgICAgICAgICAgaW1nX2hlYWx0aHkgPSBwYWxzJHNvamFfaC5wbmcsICAgICAjIHBhbGV0YSBwYXJhIGZvbGhhIHNhZGlhDQogICAgICAgICAgICAgICAgICBpbWdfc3ltcHRvbXMgPSBwYWxzJHNvamFfcy5wbmcsICAgICMgcGFsZXRhIHBhcmEgZm9saGEgZG9lbnRlDQogICAgICAgICAgICAgICAgICBpbWdfYmFja2dyb3VuZCA9IHBhbHMkc29qYV9iLnBuZykgICMgcGFsZXRhIHBhcmEgZnVuZG8NCnNldiRzZXZlcml0eQ0KDQpgYGANCg0KDQojIyBVc2FuZG8gw61uZGljZXMgZGUgaW1hZ2VtDQpgYGB7cn0NCiMgw41uZGljZSBwYXJhIHNlZ21lbnRhciBhIGZvbGhhIGRvIGZ1bmRvLCBkZXBvaXMgYSBkb2Vuw6dhIGRhIGZvbGhhDQppbWFnZV9zZWdtZW50X2l0ZXIoZm9saGEsIA0KICAgICAgICAgICAgICAgICAgIGluZGV4ID0gYygiQiIsICJOR1JESSIpLA0KICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzKQ0KDQojIElNUE9SVEFOVEU6IHRoZXNob2xkIHZhaSBhbHRlcmFyIGEgc2V2ZXJpZGFkZQ0Kc2V2MiA8LSANCiAgbWVhc3VyZV9kaXNlYXNlKGZvbGhhLA0KICAgICAgICAgICAgICAgICAgaW5kZXhfbGIgPSAiQiIsICAgICAgICAgICAgIyDDrW5kaWNlIHBhcmEgc2VnbWVudGFyIGEgZm9saGEgZG8gZnVuZG8NCiAgICAgICAgICAgICAgICAgIGluZGV4X2RoID0gIk5HUkRJIiwgICAgICAgICMgw61uZGljZSBwYXJhIHNlZ21lbnRhciBmb2xoYSBkb2VudGUgZSBzYWRpYQ0KICAgICAgICAgICAgICAgICAgdGhyZXNob2xkID0gYygiT3RzdSIsIDApKSAgIyB0aHJlc2hvbGQgcGFyYSBvcyBkb2lzIMOtbmRpY2VzLCByZXNwZWN0aXZhbWVudGUNCnNldjIkc2V2ZXJpdHkNCg0KIyBlbSBsb3RlICh1dGlsaXphbmRvIGFzIHBhbGV0YXMpDQpzZXYzIDwtIA0KICBtZWFzdXJlX2Rpc2Vhc2UocGF0dGVybiA9ICJzb3lfIiwNCiAgICAgICAgICAgICAgICAgIGRpcl9vcmlnaW5hbCA9ICJzb3liZWFuX3J1c3QiLCAgICAjIHBhc3RhIGNvbSBhcyBpbWFnZW5zIG9yaWdpbmFpcw0KICAgICAgICAgICAgICAgICAgZGlyX3Byb2Nlc3NlZCA9ICJwcm9jX3J1c3QiLCAgICAgICMgcGFzdGEgY29tIGFzIGltYWdlbnMgcHJvY2Vzc2FkYXMNCiAgICAgICAgICAgICAgICAgIHNhdmVfaW1hZ2UgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgcGxvdCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgaW1nX2hlYWx0aHkgPSBwYWxzJHNvamFfaC5wbmcsDQogICAgICAgICAgICAgICAgICBpbWdfc3ltcHRvbXMgPSBwYWxzJHNvamFfcy5wbmcsDQogICAgICAgICAgICAgICAgICBpbWdfYmFja2dyb3VuZCA9IHBhbHMkc29qYV9iLnBuZywNCiAgICAgICAgICAgICAgICAgIHBhcmFsbGVsID0gVFJVRSkNCiMgc3RhbmRhcmQgYXJlYSBkaWFncmFtcw0Kc2FkKHNldjMsIG4gPSA2KQ0KDQpzZXY0IDwtIA0KICBtZWFzdXJlX2Rpc2Vhc2UocGF0dGVybiA9ICJzb3lfIiwNCiAgICAgICAgICAgICAgICAgIGRpcl9vcmlnaW5hbCA9ICJzb3liZWFuX3J1c3QiLA0KICAgICAgICAgICAgICAgICAgcGxvdCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgaW5kZXhfbGIgPSAiQiIsDQogICAgICAgICAgICAgICAgICBpbmRleF9kaCA9ICJOR1JESSIsDQogICAgICAgICAgICAgICAgICB0aHJlc2hvbGQgPSBjKCJPdHN1IiwgMCksDQogICAgICAgICAgICAgICAgICBwYXJhbGxlbCA9IFRSVUUpDQoNCg0KIyBwYWxldGFzIHZzIMOtbmRpY2VzIGRlIGltYWdlbQ0KDQpkZiA8LSANCiAgZGF0YS5mcmFtZShwYWxldGFzID0gc2V2MyRzZXZlcml0eSRzeW1wdG9tYXRpYywNCiAgICAgICAgICAgICDDrW5kaWNlcyA9IHNldjQkc2V2ZXJpdHkkc3ltcHRvbWF0aWMpDQpkZg0KDQpnZ3Bsb3QoZGYsIGFlcyhwYWxldGFzLCDDrW5kaWNlcykpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvciA9ICJyZWQiKSArDQogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE2KSArDQogIHhsaW0oMCwgMTAwKSArDQogIHlsaW0oMCwgMTAwKSArDQogIGNvb3JkX2VxdWFsKCkNCg0KYGBgDQoNCiMjIEVtIGdyaWRzDQoNCmBgYHtyfQ0KZm9saGFfZ3JpZCA8LSBpbWFnZV9pbXBvcnQoImRpc2Vhc2Vfc2hwLmpwZyIsIHBsb3QgPSBUUlVFKQ0KDQpzZXY1IDwtIA0KICBtZWFzdXJlX2Rpc2Vhc2Vfc2hwKGZvbGhhX2dyaWQsDQogICAgICAgICAgICAgICAgICAgICAgaW5kZXhfbGIgPSAiSFVFMiIsDQogICAgICAgICAgICAgICAgICAgICAgaW5kZXhfZGggPSAiTkdSREkiLA0KICAgICAgICAgICAgICAgICAgICAgIHRocmVzaG9sZCA9IGMoIk90c3UiLCAwKSwNCiAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIgPSAxMCwNCiAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMywNCiAgICAgICAgICAgICAgICAgICAgICBucm93ID0gMywNCiAgICAgICAgICAgICAgICAgICAgICBwbG90ID0gRkFMU0UpDQpwbG90KGZvbGhhX2dyaWQpDQpwbG90KHNldjUkc2hhcGVmaWxlcykNCnBsb3RfbWVhc3VyZXMoc2V2NSwgInN5bXB0b21hdGljIikNCg0KYGBgDQoNCg0KDQo=